]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
ShellRecorder: update to use MetaCursorTracker
authorGiovanni Campagna <gcampagn@redhat.com>
Wed, 14 Aug 2013 08:34:58 +0000 (10:34 +0200)
committerGiovanni Campagna <gcampagn@redhat.com>
Mon, 19 Aug 2013 14:14:12 +0000 (16:14 +0200)
Replace more direct XFixes usage with a the appropriate abstraction
API from mutter, which is guaranteed to work in wayland too.

It doesn't yet replace pointer position tracking, although probably
it should.
Also, because now we're using Mutter API, we lose the standalone
test case.

https://bugzilla.gnome.org/show_bug.cgi?id=705911

js/ui/screencast.js
src/Makefile.am
src/shell-recorder.c
src/test-recorder.c [deleted file]

index 61dc692ef991a56b04acac50f69993d636bdb8ea..5b3c41922828b69368092caa2888a0900aa08951 100644 (file)
@@ -52,7 +52,8 @@ const ScreencastService = new Lang.Class({
     _ensureRecorderForSender: function(sender) {
         let recorder = this._recorders.get(sender);
         if (!recorder) {
-            recorder = new Shell.Recorder({ stage: global.stage });
+            recorder = new Shell.Recorder({ stage: global.stage,
+                                            screen: global.screen });
             recorder._watchNameId =
                 Gio.bus_watch_name(Gio.BusType.SESSION, sender, 0, null,
                                    Lang.bind(this, this._onNameVanished));
index 74c6c299bd638cc8031abb521c07275ec649e6e3..a5e74b9860c7971a8d9eedcea361d763e9fd4e22 100644 (file)
@@ -226,14 +226,6 @@ shell_recorder_private_sources =  \
 
 shell_private_sources += $(shell_recorder_private_sources)
 
-noinst_PROGRAMS += test-recorder
-
-test_recorder_CPPFLAGS = $(TEST_SHELL_RECORDER_CFLAGS)
-test_recorder_LDADD = $(TEST_SHELL_RECORDER_LIBS)
-
-test_recorder_SOURCES =     \
-       $(shell_recorder_sources) $(shell_recorder_private_sources) \
-       test-recorder.c
 endif BUILD_RECORDER
 
 ########################################
index 6b2bdfa643c3e8dcf43fdd6bf044eab149ed01cf..23f2c072c554a0f8439a00d366d896d3b05f6520 100644 (file)
 #include <gtk/gtk.h>
 #include <gdk/gdk.h>
 
+#include <cogl/cogl.h>
+#include <meta/screen.h>
+#include <meta/meta-cursor-tracker.h>
+
 #include "shell-recorder-src.h"
 #include "shell-recorder.h"
 
 #include <clutter/x11/clutter-x11.h>
-#include <X11/extensions/Xfixes.h>
 #include <X11/extensions/XInput.h>
 #include <X11/extensions/XInput2.h>
 
@@ -64,14 +67,13 @@ struct _ShellRecorder {
   int pointer_x;
   int pointer_y;
 
-  gboolean have_xfixes;
-  int xfixes_event_base;
-
   int xinput_opcode;
 
   GSettings *a11y_settings;
   gboolean draw_cursor;
+  MetaCursorTracker *cursor_tracker;
   cairo_surface_t *cursor_image;
+  guint8 *cursor_memory;
   int cursor_hot_x;
   int cursor_hot_y;
 
@@ -121,6 +123,7 @@ static void recorder_pipeline_closed   (RecorderPipeline *pipeline);
 
 enum {
   PROP_0,
+  PROP_SCREEN,
   PROP_STAGE,
   PROP_FRAMERATE,
   PROP_PIPELINE,
@@ -242,6 +245,8 @@ shell_recorder_finalize (GObject  *object)
 
   if (recorder->cursor_image)
     cairo_surface_destroy (recorder->cursor_image);
+  if (recorder->cursor_memory)
+    g_free (recorder->cursor_memory);
 
   recorder_set_stage (recorder, NULL);
   recorder_set_pipeline (recorder, NULL);
@@ -322,38 +327,24 @@ recorder_remove_redraw_timeout (ShellRecorder *recorder)
 static void
 recorder_fetch_cursor_image (ShellRecorder *recorder)
 {
-  XFixesCursorImage *cursor_image;
-  guchar *data;
+  CoglTexture *texture;
+  int width, height;
   int stride;
-  int i, j;
-
-  if (!recorder->have_xfixes)
-    return;
-
-  cursor_image = XFixesGetCursorImage (clutter_x11_get_default_display ());
-  if (!cursor_image)
-    return;
-
-  recorder->cursor_hot_x = cursor_image->xhot;
-  recorder->cursor_hot_y = cursor_image->yhot;
-
-  recorder->cursor_image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
-                                                       cursor_image->width,
-                                                       cursor_image->height);
-
-  /* The pixel data (in typical Xlib breakage) is longs even on
-   * 64-bit platforms, so we have to data-convert there. For simplicity,
-   * just do it always
-   */
-  data = cairo_image_surface_get_data (recorder->cursor_image);
-  stride = cairo_image_surface_get_stride (recorder->cursor_image);
-  for (i = 0; i < cursor_image->height; i++)
-    for (j = 0; j < cursor_image->width; j++)
-      *(guint32 *)(data + i * stride + 4 * j) = cursor_image->pixels[i * cursor_image->width + j];
-
-  cairo_surface_mark_dirty (recorder->cursor_image);
+  guint8 *data;
 
-  XFree (cursor_image);
+  texture = meta_cursor_tracker_get_sprite (recorder->cursor_tracker);
+  width = cogl_texture_get_width (texture);
+  height = cogl_texture_get_height (texture);
+  stride = 4 * width;
+  data = g_new (guint8, stride * height);
+  cogl_texture_get_data (texture, CLUTTER_CAIRO_FORMAT_ARGB32, stride, data);
+
+  /* FIXME: cairo-gl? */
+  recorder->cursor_image = cairo_image_surface_create_for_data (data,
+                                                                CAIRO_FORMAT_ARGB32,
+                                                                width, height,
+                                                                stride);
+  recorder->cursor_memory = data;
 }
 
 /* Overlay the cursor image on the frame. We draw the cursor image
@@ -546,6 +537,24 @@ recorder_queue_redraw (ShellRecorder *recorder)
                                              recorder_idle_redraw, recorder, NULL);
 }
 
+static void
+on_cursor_changed (MetaCursorTracker *tracker,
+                   ShellRecorder     *recorder)
+{
+  if (recorder->cursor_image)
+    {
+      cairo_surface_destroy (recorder->cursor_image);
+      recorder->cursor_image = NULL;
+    }
+  if (recorder->cursor_memory)
+    {
+      g_free (recorder->cursor_memory);
+      recorder->cursor_memory = NULL;
+    }
+
+  recorder_queue_redraw (recorder);
+}
+
 /* We use an event filter on the stage to get the XFixesCursorNotifyEvent
  * and also to track cursor position (when the cursor is over the stage's
  * input area); tracking cursor position here rather than with ClutterEvent
@@ -567,23 +576,8 @@ recorder_event_filter (XEvent        *xev,
       xev->xcookie.extension == recorder->xinput_opcode)
     input_event = (XIEvent *) xev->xcookie.data;
 
-  if (xev->xany.type == recorder->xfixes_event_base + XFixesCursorNotify)
-    {
-      XFixesCursorNotifyEvent *notify_event = (XFixesCursorNotifyEvent *)xev;
-
-      if (notify_event->subtype == XFixesDisplayCursorNotify)
-        {
-          if (recorder->cursor_image)
-            {
-              cairo_surface_destroy (recorder->cursor_image);
-              recorder->cursor_image = NULL;
-            }
-
-          recorder_queue_redraw (recorder);
-        }
-    }
-  else if (input_event != NULL &&
-           input_event->evtype == XI_Motion)
+  if (input_event != NULL &&
+      input_event->evtype == XI_Motion)
     {
       XIDeviceEvent *device_event = (XIDeviceEvent *) input_event;
       if (device_event->deviceid == VIRTUAL_CORE_POINTER_ID)
@@ -807,14 +801,6 @@ recorder_set_stage (ShellRecorder *recorder,
 
       recorder_update_size (recorder);
 
-      recorder->have_xfixes = XFixesQueryExtension (clutter_x11_get_default_display (),
-                                                    &recorder->xfixes_event_base,
-                                                    &error_base);
-      if (recorder->have_xfixes)
-        XFixesSelectCursorInput (clutter_x11_get_default_display (),
-                                   clutter_x11_get_stage_window (stage),
-                                 XFixesDisplayCursorNotifyMask);
-
       if (XQueryExtension (clutter_x11_get_default_display (),
                            "XInputExtension",
                            &recorder->xinput_opcode,
@@ -843,6 +829,22 @@ recorder_set_stage (ShellRecorder *recorder,
     }
 }
 
+static void
+recorder_set_screen (ShellRecorder *recorder,
+                     MetaScreen    *screen)
+{
+  MetaCursorTracker *tracker;
+
+  tracker = meta_cursor_tracker_get_for_screen (screen);
+
+  if (tracker == recorder->cursor_tracker)
+    return;
+
+  recorder->cursor_tracker = tracker;
+  g_signal_connect_object (tracker, "cursor-changed",
+                           G_CALLBACK (on_cursor_changed), recorder, 0);
+}
+
 static void
 recorder_set_framerate (ShellRecorder *recorder,
                         int framerate)
@@ -918,6 +920,9 @@ shell_recorder_set_property (GObject      *object,
 
   switch (prop_id)
     {
+    case PROP_SCREEN:
+      recorder_set_screen (recorder, g_value_get_object (value));
+      break;
     case PROP_STAGE:
       recorder_set_stage (recorder, g_value_get_object (value));
       break;
@@ -979,6 +984,14 @@ shell_recorder_class_init (ShellRecorderClass *klass)
   gobject_class->get_property = shell_recorder_get_property;
   gobject_class->set_property = shell_recorder_set_property;
 
+  g_object_class_install_property (gobject_class,
+                                   PROP_SCREEN,
+                                   g_param_spec_object ("screen",
+                                                        "Screen",
+                                                        "Screen to record",
+                                                        META_TYPE_SCREEN,
+                                                        G_PARAM_WRITABLE));
+
   g_object_class_install_property (gobject_class,
                                    PROP_STAGE,
                                    g_param_spec_object ("stage",
diff --git a/src/test-recorder.c b/src/test-recorder.c
deleted file mode 100644 (file)
index 86f9379..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-#define GST_USE_UNSTABLE_API
-#include "shell-recorder.h"
-#include <clutter/clutter.h>
-#include <gtk/gtk.h>
-#include <gst/gst.h>
-
-/* Very simple test of the ShellRecorder class; shows some text strings
- * moving around and records it.
- */
-static ShellRecorder *recorder = NULL;
-
-static gboolean
-stop_recording_timeout (ClutterActor *stage)
-{
-  if (recorder)
-    {
-      shell_recorder_close (recorder);
-
-      /* quit when the recorder finishes closing
-       */
-      g_object_weak_ref (G_OBJECT (recorder),
-                         (GWeakNotify)
-                         clutter_actor_destroy,
-                         stage);
-
-      g_object_unref (recorder);
-    }
-  else
-    {
-      clutter_actor_destroy (stage);
-    }
-
-  return FALSE;
-}
-
-static void
-on_animation_completed (ClutterAnimation *animation,
-                        ClutterStage     *stage)
-{
-  g_timeout_add (1000, (GSourceFunc) stop_recording_timeout, stage);
-}
-
-static void
-on_stage_realized (ClutterActor *stage,
-                   gpointer      data)
-{
-  recorder = shell_recorder_new (CLUTTER_STAGE (stage));
-  shell_recorder_set_file_template (recorder, "test-recorder.webm");
-  shell_recorder_record (recorder, NULL);
-}
-
-int main (int argc, char **argv)
-{
-  ClutterActor *stage;
-  ClutterActor *text;
-  ClutterAnimation *animation;
-  ClutterColor red, green, blue;
-
-  gtk_init (&argc, &argv);
-  gst_init (&argc, &argv);
-  if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
-    return 1;
-
-  clutter_color_from_string (&red, "red");
-  clutter_color_from_string (&green, "green");
-  clutter_color_from_string (&blue, "blue");
-  stage = clutter_stage_new ();
-  g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
-
-  text = g_object_new (CLUTTER_TYPE_TEXT,
-                      "text", "Red",
-                      "font-name", "Sans 40px",
-                      "color", &red,
-                      NULL);
-  clutter_actor_add_child (stage, text);
-  animation = clutter_actor_animate (text,
-                                    CLUTTER_EASE_IN_OUT_QUAD,
-                                    3000,
-                                    "x", 320.0,
-                                    "y", 240.0,
-                                    NULL);
-  g_signal_connect (animation, "completed",
-                   G_CALLBACK (on_animation_completed), stage);
-
-  text = g_object_new (CLUTTER_TYPE_TEXT,
-                      "text", "Blue",
-                      "font-name", "Sans 40px",
-                      "color", &blue,
-                      "x", 640.0,
-                      "y", 0.0,
-                      NULL);
-  clutter_actor_set_anchor_point_from_gravity (text, CLUTTER_GRAVITY_NORTH_EAST);
-  clutter_actor_add_child (stage, text);
-  animation = clutter_actor_animate (text,
-                                    CLUTTER_EASE_IN_OUT_QUAD,
-                                    3000,
-                                    "x", 320.0,
-                                    "y", 240.0,
-                                    NULL);
-
-  text = g_object_new (CLUTTER_TYPE_TEXT,
-                      "text", "Green",
-                      "font-name", "Sans 40px",
-                      "color", &green,
-                      "x", 0.0,
-                      "y", 480.0,
-                      NULL);
-  clutter_actor_set_anchor_point_from_gravity (text, CLUTTER_GRAVITY_SOUTH_WEST);
-  clutter_actor_add_child (stage, text);
-  animation = clutter_actor_animate (text,
-                                    CLUTTER_EASE_IN_OUT_QUAD,
-                                    3000,
-                                    "x", 320.0,
-                                    "y", 240.0,
-                                    NULL);
-
-  g_signal_connect_after (stage, "realize",
-                          G_CALLBACK (on_stage_realized), NULL);
-
-  clutter_actor_show (stage);
-
-  clutter_main ();
-
-  return 0;
-}